package com.mingqijia.gassafety.webserver.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.EnumUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gap.basic.exception.BizException;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.util.StringUtil;
import com.mingqijia.gassafety.db.entity.JvInfo;
import com.mingqijia.gassafety.db.entity.OperationLog;
import com.mingqijia.gassafety.db.entity.vo.OperationLogVO;
import com.mingqijia.gassafety.db.mapper.OperationLogMapper;
import com.mingqijia.gassafety.shared.constant.OperationTypeEnum;
import com.mingqijia.gassafety.shared.utils.ApplicationUtils;
import com.mingqijia.gassafety.shared.utils.commonUtils.BeanConvertUtils;
import com.mingqijia.gassafety.shared.utils.commonUtils.PageUtil;
import com.mingqijia.gassafety.webserver.request.OperationLogRequest;
import com.mingqijia.gassafety.webserver.response.OperationLogResponse;
import com.mingqijia.gassafety.webserver.service.JvInfoService;
import com.mingqijia.gassafety.webserver.service.OperationLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

import static com.mingqijia.gassafety.shared.constant.OperationTypeEnum.OPERATION_TYPE_17;

/**
 * @program: gassafety
 * @description: 日志记录
 * @author: Mr.Wang
 * @create: 2023-02-08 15:44
 **/
@Service
@Slf4j
public class OperationLogServiceImpl extends ServiceImpl<OperationLogMapper, OperationLog> implements OperationLogService {

    @Autowired
    JvInfoService jvInfoService;

    @Override
    public void insertLog(OperationLogVO vo) {
        log.info("日志记录: OperationLogVO: {}", JSONObject.toJSONString(vo));
        String spId = ApplicationUtils.getWorkingSpId();
        if (StringUtils.isEmpty(spId)) {
            spId = vo.getSpId();
        }
        List<Integer> codeList = vo.getCodeList();
        List<String> info = OperationTypeEnum.getInfo(codeList.get(0)); //传入的codeList一定是同一菜单下;

        //多个操作详情进行合并
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < codeList.size(); i++) {
            Integer code = codeList.get(i);
            List<String> logInfo = OperationTypeEnum.getInfo(code);
            if (CollectionUtil.isEmpty(logInfo)){
                log.info("code:{}无对应操作",codeList);
                return;
            }

            String detail = logInfo.get(2);
            if (code.equals(OPERATION_TYPE_17.getCode())){ // 联系人级别发生变化
                detail = String.format(detail, vo.getOperationBefore(), vo.getOperationAfter());
            }

            sb.append(detail);
            if ( i != (codeList.size()-1) )  sb.append(";");//不是最后一位,分号隔开

        }

        OperationLog operationLog = new OperationLog();

        //对于 并非登录后台账号的操作日志,需要在入参vo中设置
        if (StringUtil.isNotEmpty(vo.getOperationPersonCode()) && StringUtil.isNotEmpty(vo.getOperationPersonName())){
            operationLog.setOperationPersonCode(vo.getOperationPersonCode());
            operationLog.setOperationPersonName(vo.getOperationPersonName());
        }else {
            operationLog.setOperationPersonCode( ApplicationUtils.getWorkingUser().getUsername());
            operationLog.setOperationPersonName(ApplicationUtils.getWorkingUser().getName());
        }
        operationLog.setOperationMenu(info.get(0));
        operationLog.setOperationType(info.get(1));
        operationLog.setLogDetail(sb.toString());

        operationLog.setTableName(vo.getTableName());
        operationLog.setTableKey(vo.getTableKey());
        //如果有值,存入
        if (StringUtil.isNotEmpty(vo.getOperationBefore()) && StringUtil.isNotEmpty(vo.getOperationAfter())){
            operationLog.setOperationBefore(vo.getOperationBefore());
            operationLog.setOperationAfter(vo.getOperationAfter());
        }
        operationLog.setSpId(spId);

        this.save(operationLog);
        log.info("新增日志记录:{}",JSONObject.toJSONString(operationLog));

    }

    @Override
    public PageUtil<OperationLogResponse> getList(OperationLogRequest request) {
        log.info("查询日志信息,入参:{}", JSONObject.toJSONString(request));
        String spId = ApplicationUtils.getWorkingSpId();
        if (!"0".equals(spId)){
            throw new BizException("无权限查看日志");
        }
        QueryWrapper<OperationLog> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().between(request.getCreatedAtStart()!=null, OperationLog::getCreatedAt,request.getCreatedAtStart(),request.getCreatedAtEnd());
        if (StringUtil.isNotEmpty(request.getOperationPerson())){
            queryWrapper.lambda().and(
                    wrapper -> wrapper.eq(OperationLog::getOperationPersonCode,request.getOperationPerson())
                            .or().eq(OperationLog::getOperationPersonName,request.getOperationPerson()));
        }
        queryWrapper.lambda().eq(StringUtil.isNotEmpty(request.getOperationType()), OperationLog::getOperationType,request.getOperationType())
        .orderByDesc(OperationLog::getCreatedAt);

        Page<OperationLog> page = PageHelper.startPage(request.getPage(), request.getPageSize());
        List<OperationLog> list = this.list(queryWrapper);
        List<OperationLogResponse> operationLogResponses = BeanConvertUtils.convertListTo(list, OperationLogResponse::new);
        PageUtil<OperationLogResponse> pageUtil = new PageUtil<>();
        if (CollectionUtil.isEmpty(operationLogResponses)){
            return pageUtil;
        }
        List<String> spIdList = operationLogResponses.stream().map(OperationLogResponse::getSpId).collect(Collectors.toList());
        QueryWrapper<JvInfo> jvInfoQueryWrapper = new QueryWrapper<>();
        jvInfoQueryWrapper.lambda().in(JvInfo::getSpId, spIdList).eq(JvInfo::getIsDeleted,false);
        List<JvInfo> jvInfoList = jvInfoService.list(jvInfoQueryWrapper);
        Map<String, JvInfo> jvInfoMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(jvInfoList)) {
            jvInfoMap = jvInfoList.stream().collect(Collectors.toMap(JvInfo::getSpId, JvInfo -> JvInfo, (a1, a2) -> a1));
        }
        for (OperationLogResponse response : operationLogResponses) {
            if (jvInfoMap.containsKey(response.getSpId())) {
                response.setSpIdName(jvInfoMap.get(response.getSpId()).getName());
            }
        }


        pageUtil.setPage(request.getPage());
        pageUtil.setPageSize(request.getPageSize());
        pageUtil.setTotal(page.getTotal());
        pageUtil.setList(operationLogResponses);

        return pageUtil;
    }

    @Override
    public void saveShutDownOperation(Integer operationCode) {
        OperationLogVO logVO = new OperationLogVO();
        List<Integer> logCodeList = new ArrayList<>();
        logCodeList.add(operationCode);
        logVO.setCodeList(logCodeList);
        this.insertLog(logVO);
    }

    @Override
    public List<String> getTypeList() {
        Map<String, Object> operationType = EnumUtil.getNameFieldMap(OperationTypeEnum.class, "operationType");
        Set<Map.Entry<String, Object>> entries = operationType.entrySet();
        ArrayList<String> list = new ArrayList<>();
        for (Map.Entry<String, Object> entry : entries) {
            list.add(entry.getValue().toString());
        }
        List<String> data = list.stream().distinct().collect(Collectors.toList());
        return data;
    }
}
